package com.turing.common.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SnowFlakeUtil {

    public static void main(String[] args) {
        Date date = new Date(1586361600000L);
        System.out.println(date);

        System.out.println(SnowFlakeUtil.datetimeBySnowId(939139824206479383L));
        System.out.println(SnowFlakeUtil.datetimeByTimestamp(939139824206479383L));
        System.out.println(SnowFlakeUtil.timestamp(939139824206479383L));
        System.out.println(SnowFlakeUtil.toBinaryStringWithSplitSymbol(939139824206479383L));
        System.out.println(new Date(SnowFlakeUtil.datetimeByTimestamp(1590616515L)));
        System.out.println(monthBySnowId(939139824206479383L));
    }

    /**
     * 开始时间截 (2015-01-01)
     */
    private static long TWEPOCH = 1420041600000L;
    /**
     * timestamp bit长度
     */
    public static int TIMESTAMP_BIT = 41;
    /**
     * 数据中心bit长度
     */
    public static int DATA_CENTER_BIT = 5;
    /**
     * 机器bit长度
     */
    public static int WORKER_BIT = 5;
    /**
     * 每ms序号bit长度
     */
    public static int SEQ_BIT = 12;
    /**
     * 算法的总bit长度
     */
    public static int FULL_BIT = 64;



    /**
     * 以二进制位带-分隔符形式返回id
     *
     * @param snowId
     * @return
     */
    static String toBinaryStringWithSplitSymbol(long snowId) {

        char[] bId = Long.toBinaryString(snowId).toCharArray();
        StringBuilder sb = new StringBuilder();
        //标志位
        sb.append("0").append('-');

        //时间戳
        int timestamp = bId.length - (WORKER_BIT + DATA_CENTER_BIT + SEQ_BIT);
        int zero = TIMESTAMP_BIT - timestamp;
        //时间戳前面补全0
        for (int i = 0; i < zero; i++) {
            sb.append(0);
        }
        for (int i = 0; i < timestamp; i++) {
            sb.append(bId[i]);
        }
        sb.append('-');

        //data center + work
        int workLength = WORKER_BIT + DATA_CENTER_BIT;
        for (int i = timestamp; i < timestamp + workLength; i++) {
            sb.append(bId[i]);
        }
        sb.append('-');
        //num seq
        for (int i = timestamp + workLength; i < bId.length; i++) {
            sb.append(bId[i]);
        }
        return sb.toString();
    }

    /**
     * 从雪花id中计算出规定起始时间戳的时间戳
     * 起始时间戳见EPOCH字段
     *
     * @param snowId 雪花算法生成的id
     * @return
     */
    public static long timestamp(long snowId) {
        return (snowId  >> 22) + TWEPOCH;
    }

    /**
     * 根据雪花id的时间戳，计算真实时间戳，从1970.。。开始
     *
     * @param timestamp 雪花算法的时间戳
     * @return
     */
    public static long datetimeByTimestamp(long timestamp) {
        return timestamp + TWEPOCH;
    }

    /**
     * 根据雪花id输出真实时间戳，从19.。。
     *
     * @param snowId
     * @return
     */
    public static long datetimeBySnowId(long snowId) {
        return timestamp(snowId) + TWEPOCH;
    }

    public static String monthBySnowId(long snowId) {
        Date date = new Date(SnowFlakeUtil.timestamp(snowId));
        DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
        return dateFormat.format(date);
    }



}
